package com.english.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.english.entity.ClassAttendance;
import com.english.entity.StudentClassHours;
import com.english.entity.ClassHoursLog;
import com.english.entity.Lesson;
import com.english.entity.AttendanceLog;
import com.english.mapper.ClassAttendanceMapper;
import com.english.mapper.StudentClassHoursMapper;
import com.english.mapper.ClassHoursLogMapper;
import com.english.mapper.LessonMapper;
import com.english.mapper.AttendanceLogMapper;
import com.english.service.AttendanceService;
import com.english.service.LessonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 签到签退服务实现类
 *
 * @author wlq
 * @since 2025-08-08
 */
@Service
public class AttendanceServiceImpl implements AttendanceService {

    @Autowired
    private ClassAttendanceMapper classAttendanceMapper;

    @Autowired
    private StudentClassHoursMapper studentClassHoursMapper;

    @Autowired
    private ClassHoursLogMapper classHoursLogMapper;
    
    @Autowired
    private LessonMapper lessonMapper;
    
    @Autowired
    private LessonService lessonService;
    
    @Autowired
    private AttendanceLogMapper attendanceLogMapper;

    @Override
    @Transactional
    public Map<String, Object> signIn(Long studentId, Long adminId) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            LocalDate today = LocalDate.now();
            LocalDateTime now = LocalDateTime.now();
            
            System.out.println("开始处理学生签到，学生ID: " + studentId + ", 管理员ID: " + adminId + ", 日期: " + today);
            
            // 检查今日是否已有未签退的签到记录（修复逻辑）
            QueryWrapper<ClassAttendance> wrapper = new QueryWrapper<>();
            wrapper.eq("student_id", studentId)
                   .eq("attendance_date", today)
                   .eq("status", ClassAttendance.AttendanceStatus.SIGNED_IN) // 只查找未签退的记录
                   .orderByDesc("create_time")
                   .last("LIMIT 1");
            ClassAttendance existingSignedIn = classAttendanceMapper.selectOne(wrapper);
            
            if (existingSignedIn != null) {
                System.out.println("学生" + studentId + "已有未签退的签到记录，ID: " + existingSignedIn.getId());
            }
            
            // 只有存在未签退的签到记录时才阻止新的签到
            if (existingSignedIn != null) {
                result.put("success", false);
                result.put("message", "您已签到，请先签退后再进行签到");
                return result;
            }
            
            // 获取学生的班级信息（选择第一个班级）
            QueryWrapper<StudentClassHours> hoursWrapper = new QueryWrapper<>();
            hoursWrapper.eq("student_id", studentId)
                       .orderByAsc("id")
                       .last("LIMIT 1");
            StudentClassHours studentHours = studentClassHoursMapper.selectOne(hoursWrapper);
            
            if (studentHours == null) {
                System.out.println("学生" + studentId + "的班级信息不存在");
                result.put("success", false);
                result.put("message", "学生班级信息不存在");
                return result;
            }
            
            // 检查学生剩余课时
            Lesson lesson = lessonMapper.selectByStudentId(studentId);
            if (lesson == null) {
                System.out.println("学生" + studentId + "的课时信息不存在");
                result.put("success", false);
                result.put("message", "学生课时信息不存在");
                return result;
            }
            
            if (lesson.getRemainingHours() <= 0) {
                System.out.println("学生" + studentId + "剩余课时不足: " + lesson.getRemainingHours());
                result.put("success", false);
                result.put("message", "剩余课时不足，无法签到");
                return result;
            }
            
            System.out.println("学生" + studentId + "课时检查通过，剩余课时: " + lesson.getRemainingHours());
            
            // 创建签到记录
            ClassAttendance attendance = new ClassAttendance();
            attendance.setStudentId(studentId);
            attendance.setClassId(studentHours.getClassId()); // 使用student_class_hours的班级信息
            attendance.setAttendanceDate(today);
            attendance.setSignInTime(now);
            attendance.setStatus(ClassAttendance.AttendanceStatus.SIGNED_IN);
            attendance.setNotes("管理员签到");
            
            classAttendanceMapper.insert(attendance);
            System.out.println("学生" + studentId + "签到记录创建成功，记录ID: " + attendance.getId());
            
            // 记录签到日志
            createAttendanceLog(studentId, adminId, attendance.getId(), 
                              AttendanceLog.ActionType.SIGN_IN, now, 
                              0, lesson.getRemainingHours(), lesson.getRemainingHours(), 
                              "管理员操作签到");
            
            result.put("success", true);
            result.put("message", "签到成功");
            result.put("attendanceId", attendance.getId());
            
        } catch (Exception e) {
            System.err.println("学生" + studentId + "签到失败: " + e.getMessage());
            e.printStackTrace();
            result.put("success", false);
            result.put("message", "签到失败：" + e.getMessage());
        }
        
        return result;
    }

    @Override
    @Transactional
    public Map<String, Object> signOut(Long studentId, Long adminId) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            LocalDate today = LocalDate.now();
            LocalDateTime now = LocalDateTime.now();
            
            // 检查今日是否有未签退的签到记录
            QueryWrapper<ClassAttendance> wrapper = new QueryWrapper<>();
            wrapper.eq("student_id", studentId)
                   .eq("attendance_date", today)
                   .orderByDesc("create_time")
                   .last("LIMIT 1");
            ClassAttendance attendance = classAttendanceMapper.selectOne(wrapper);
            
            if (attendance == null || attendance.getStatus() != ClassAttendance.AttendanceStatus.SIGNED_IN) {
                result.put("success", false);
                result.put("message", "请先签到后再进行签退");
                return result;
            }
            
            // 更新签退时间
            attendance.setSignOutTime(now);
            attendance.setStatus(ClassAttendance.AttendanceStatus.SIGNED_OUT);
            attendance.setNotes("管理员签退");
            classAttendanceMapper.updateById(attendance);
            
            // 扣除课时
            Map<String, Object> hoursResult = deductHours(studentId, attendance.getId());
            if (!(Boolean) hoursResult.get("success")) {
                result.put("success", false);
                result.put("message", "签退成功，但扣除课时失败：" + hoursResult.get("message"));
                return result;
            }
            
            // 记录签退日志
            Map<String, Object> updatedHours = (Map<String, Object>) hoursResult.get("updatedHours");
            Integer hoursDeducted = (Integer) hoursResult.get("hoursDeducted");
            Integer beforeHours = (Integer) hoursResult.get("beforeHours");
            Integer afterHours = (Integer) updatedHours.get("remainingHours");
            
            createAttendanceLog(studentId, adminId, attendance.getId(), 
                              AttendanceLog.ActionType.SIGN_OUT, now, 
                              hoursDeducted != null ? hoursDeducted : 0, 
                              beforeHours, afterHours, 
                              "管理员操作签退");
            
            result.put("success", true);
            result.put("message", hoursResult.get("message")); // 使用扣课时方法返回的消息
            result.put("updatedHours", hoursResult.get("updatedHours"));
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "签退失败：" + e.getMessage());
        }
        
        return result;
    }

    /**
     * 扣除课时
     */
    private Map<String, Object> deductHours(Long studentId, Long attendanceId) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 获取学生总体课时信息（lesson表）
            Lesson lesson = lessonMapper.selectByStudentId(studentId);
            
            if (lesson == null) {
                result.put("success", false);
                result.put("message", "学生课时信息不存在");
                return result;
            }
            
            if (lesson.getRemainingHours() <= 0) {
                // 课时不足时，允许签退但不扣课时
                result.put("success", true);
                result.put("message", "签退成功，但因剩余课时不足未扣除课时");
                result.put("hoursDeducted", 0);
                result.put("beforeHours", lesson.getRemainingHours());
                
                Map<String, Object> updatedHours = new HashMap<>();
                updatedHours.put("remainingHours", lesson.getRemainingHours());
                updatedHours.put("usedHours", lesson.getUsedHours());
                updatedHours.put("totalHours", lesson.getTotalHours());
                result.put("updatedHours", updatedHours);
                
                return result;
            }
            
            // 记录扣除前的课时
            int beforeRemaining = lesson.getRemainingHours();
            int beforeUsed = lesson.getUsedHours();
            
            // 更新课时
            lesson.setRemainingHours(beforeRemaining - 1);
            lesson.setUsedHours(beforeUsed + 1);
            lessonMapper.updateById(lesson);
            
            // 记录课时变动日志（暂时注释掉，避免数据库约束问题）
            /*
            ClassHoursLog log = new ClassHoursLog();
            log.setStudentId(studentId);
            log.setClassId(studentHours.getClassId());
            log.setChangeValue(-1); // 扣除1课时
            log.setChangeType(ClassHoursLog.ChangeType.SIGN_OUT);
            log.setTitle("签退扣课时");
            log.setDescription("学生签退自动扣除1课时");
            log.setBeforeHours(beforeRemaining);
            log.setAfterHours(beforeRemaining - 1);
            log.setAttendanceId(attendanceId);
            
            classHoursLogMapper.insert(log);
            */
            
            // 返回更新后的课时信息
            Map<String, Object> updatedHours = new HashMap<>();
            updatedHours.put("remainingHours", lesson.getRemainingHours());
            updatedHours.put("usedHours", lesson.getUsedHours());
            updatedHours.put("totalHours", lesson.getTotalHours());
            
            result.put("success", true);
            result.put("message", "签退成功，已扣减1课时");
            result.put("hoursDeducted", 1);
            result.put("beforeHours", beforeRemaining);
            result.put("updatedHours", updatedHours);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "扣除课时失败：" + e.getMessage());
        }
        
        return result;
    }

    @Override
    public List<ClassAttendance> getTodayAttendance(LocalDate date) {
        return classAttendanceMapper.getTodayAttendance(date);
    }

    @Override
    public List<ClassAttendance> getStudentAttendanceHistory(Long studentId) {
        return classAttendanceMapper.getStudentAttendanceHistory(studentId);
    }

    @Override
    public Map<String, Object> getTodayStats(LocalDate date) {
        Map<String, Object> stats = new HashMap<>();
        
        List<ClassAttendance> todayAttendance = getTodayAttendance(date);
        
        long totalStudents = todayAttendance.size();
        long signedInCount = todayAttendance.stream()
                .filter(a -> a.getStatus() == ClassAttendance.AttendanceStatus.SIGNED_IN)
                .count();
        long signedOutCount = todayAttendance.stream()
                .filter(a -> a.getStatus() == ClassAttendance.AttendanceStatus.SIGNED_OUT)
                .count();
        
        stats.put("totalStudents", totalStudents);
        stats.put("signedInCount", signedInCount);
        stats.put("signedOutCount", signedOutCount);
        
        return stats;
    }

    /**
     * 创建签到签退日志
     */
    private void createAttendanceLog(Long studentId, Long adminId, Long attendanceId, 
                                   AttendanceLog.ActionType actionType, LocalDateTime actionTime,
                                   Integer hoursDeducted, Integer beforeHours, Integer afterHours, 
                                   String notes) {
        AttendanceLog log = new AttendanceLog();
        log.setStudentId(studentId);
        log.setAdminId(adminId);
        log.setAttendanceId(attendanceId);
        log.setActionType(actionType);
        log.setActionTime(actionTime);
        log.setHoursDeducted(hoursDeducted);
        log.setBeforeRemainingHours(beforeHours);
        log.setAfterRemainingHours(afterHours);
        log.setNotes(notes);
        
        attendanceLogMapper.insert(log);
    }

    @Override
    public List<AttendanceLog> getStudentAttendanceLogs(Long studentId) {
        return attendanceLogMapper.getLogsByStudentId(studentId);
    }

    @Override
    public List<AttendanceLog> getTodayAttendanceLogs(LocalDate date) {
        return attendanceLogMapper.getTodayLogs(date);
    }

    @Override
    public List<AttendanceLog> getRecentAttendanceLogs(Integer limit) {
        return attendanceLogMapper.getRecentLogs(limit);
    }
} 